package WhiskeyGui;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;

/**
 * User: Mike
 * Date: 12/18/11
 */

// todo: Update in data.
// todo: define objective function RMSE
// todo: optimize params

public class KalmanCalibration {

    double transCov00 = 1.0;
    double transCov01 = 1.0;
    double transCov10 = 0.0;
    double transCov11 = 1.0;

    double obsCov00 = 1.0;
    double obsCov01 = 1.0;
    double obsCov10 = 0.0;
    double obsCov11 = 1.0;

    private static ArrayList<Double> tempTCArr = new ArrayList<Double>();                    // don't have to read in all the data for the type of plotting I'm doing now
    private static ArrayList<Double> kalmanCArr = new ArrayList<Double>();
    private static ArrayList<Double> milliTimeArr = new ArrayList<Double>();

    double dt;
    double tV;

    public static void main(String[] args) {
        KalmanCalibration kC = new KalmanCalibration();
        kC.Read();
        kC.getKalmanSet();

    }

    private void getKalmanSet() {
        for (int i = 0; i < tempTCArr.size(); i++) {
            if (i > 0) {
                dt = (milliTimeArr.get(i) - milliTimeArr.get(i - 1));
                tV = (tempTCArr.get(i) - tempTCArr.get(i - 1)) / dt;
            } else {
                dt = 1000;
                tV = 0.0;
            }
            double[] obs = new double[2];
            obs[0] = tempTCArr.get(i);
            obs[1] = tV;
            KalmanFilter kf = new KalmanFilter(obs, obsCovariance());
            kf.predict(transMatrix(), transCov());
            kf.update(observation(), obsMatrix(), obsCovariance(), projection());
            kalmanCArr.add(kf.getStateVector()[0]);
        }
    }

    private void calcRMSE(){

//     ArrayList<Double> error = new ArrayList<Double>();
//        for(int i=0;i<kalmanCArr.size();i++){
//                    double tmp =
//        }
//        double tmp =
//        error.add()
    }
    public KalmanCalibration() {
        cleanUpArrays();
    }

    private double[][] transMatrix() {
        double[][] trans = new double[2][2];
        trans[0][0] = 1.0;
//        trans[0][1] = Data.dt;
        trans[1][0] = 0.0;
        trans[1][1] = 1.0;
        return trans;
    }

    private double[][] transCov() {
        double[][] transC = new double[2][2];
        transC[0][0] = transCov00;
        transC[0][1] = transCov01;
        transC[1][0] = transCov10;
        transC[1][1] = transCov11;
        return transC;
    }


    private double[][] projection() {
        double[][] proj = new double[2][2];
        proj[0][0] = 1.0;
        proj[0][1] = 0.0;
        proj[1][0] = 0.0;
        proj[1][1] = 1.0;
        return proj;
    }

    private double[] observation() {
        double[] obs = new double[2];
//        obs[0] = Data.tempTC;
//        obs[1] = Data.tVelocity;
//        obs[1] = 0.0;
        return obs;
    }

    private double[][] obsCovariance() {                               // todo need to figure out what the observation() covariance matrix is
        double[][] obsCov = new double[2][2];                          // todo then write this out to file & put it on the chart
        obsCov[0][0] = obsCov00;                                              // todo i should also increase the sensitivity to the writes so that we're putting out more data'
        obsCov[0][1] = obsCov01;
        obsCov[1][0] = obsCov10;                                            // todo i may need a calibration button
        obsCov[1][1] = obsCov11;
        return obsCov;
    }

    private double[][] obsMatrix() {
        double[][] obsCov = new double[2][2];
        obsCov[0][0] = 1.0;
        obsCov[0][1] = 0.0;
        obsCov[1][0] = 0.0;
        obsCov[1][1] = 1.0;
        return obsCov;
    }


    public void Read() {
        BufferedReader readbuffer = null;
        String filePathName = "C:\\WhiskeyData\\calibration.txt";

        try {
            readbuffer = new BufferedReader(new FileReader(filePathName));      //	"" + DatFile.Path[DatFile.Index] + "\\" + DatFile.Name[DatFile.Index]));
        } catch (FileNotFoundException e1) {
            System.out.println("File not found:" + filePathName);
            e1.printStackTrace();
        }
        String strRead;
        int i = 0;                         // where we are in the file
        int j = 0;                         // where we are in the data
        int k = 0;                         // index to import next set of data aquisition initialization

        try {
            while ((strRead = readbuffer.readLine()) != null) {
                String splitarray[] = strRead.split("\t");
                if (k == 0) {        // header
                    // datetime	millitime   kalman	columnC	columnF	ambientC	ambientF	bottleNumber	correctedAbv	uncorrectedAbv	distillateTempC	boilerTempC
                    //	0		1	        2		3		4			5			6				7				8				9				10
                    cleanUpArrays();
                }
                if (k > 1) {
                    if (splitarray.length == 13) {                         // check to make sure there is data there
                        milliTimeArr.add(Double.parseDouble(splitarray[1].trim()));
                        tempTCArr.add(Double.parseDouble(splitarray[3].trim()));
                        j++;
                    }
                }
                k = k + 1;
                i = i + 1;
            }
            readbuffer.close();
        } catch (IOException e) {
            e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
        }
    }

    private static void cleanUpArrays() {
        milliTimeArr.clear();
        tempTCArr.clear();
        kalmanCArr.clear();
    }


}
